import jsPDF from 'jspdf'
import html2canvas from 'html2canvas'

/*
 * 使用说明
 * ele:需要导出pdf的容器元素(dom节点 不是id)
 * pdfFileName: 导出文件的名字 通过调用outPutPdfFn方法也可传参数改变
 * splitClassName: 避免分段截断的类名 当pdf有多页时需要传入此参数 , 避免pdf分页时截断元素  如表格<tr class="itemClass"></tr>
 * 调用方式 先 let pdf = new PdfLoader(ele, 'pdf' ,'itemClass');
 * 若想改变pdf名称 pdf.outPutPdfFn(fileName);  outPutPdfFn方法返回一个promise 可以使用then方法处理pdf生成后的逻辑
 * */
class PdfLoader {
  constructor(ele, pdfFileName, splitClassName, breakClassName) {
    this.ele = ele
    this.ele.style.height = 'initial'
    this.pdfFileName = pdfFileName
    this.splitClassName = splitClassName
    this.breakClassName = breakClassName
    this.A4_WIDTH = 592.28
    this.A4_HEIGHT = 841.89
  }

  async getPDF() {
    let ele = this.ele
    let pdfFileName = this.pdfFileName

    let pdf = new jsPDF('p', 'pt', 'a4')

    const canvas = await html2canvas(ele, {
      dpi: window.devicePixelRatio, // 使用设备的实际 dpi
      // height: pageHeight,
      scale: 2, // 提高 scale 值以增加清晰度
      useCORS: true,
      x: 0,
      y: 0,
      // y: offsetHeight,
    })
    let contentWidth = canvas.width
    let contentHeight = canvas.height
    let imgWidth = this.A4_WIDTH - 20
    let imgHeight =
      Math.floor((this.A4_WIDTH / contentWidth) * contentHeight) - 20
    let pageData = canvas.toDataURL('image/jpeg', 1.0)

    //页面偏移
    let offsetHeight = 0
    let leftHeight = contentHeight
    let pageHeight = (contentWidth / this.A4_WIDTH) * this.A4_HEIGHT

    // 分页
    while (leftHeight > 0) {
      pdf.addImage(pageData, 'JPEG', 10, offsetHeight, imgWidth, imgHeight)
      leftHeight -= pageHeight
      offsetHeight -= this.A4_HEIGHT - 10
      //避免添加空白页
      if (leftHeight > 0) {
        pdf.addPage()
      }
    }
    await pdf.save(pdfFileName + '.pdf', { returnPromise: true })
  }

  getPageHeight() {
    let target = this.ele
    return Math.floor((target.scrollWidth / this.A4_WIDTH) * this.A4_HEIGHT)
  }

  setTableHeight(
    dataList,
    dataKey,
    topClass,
    headerClass,
    mainClass,
    rowClass
  ) {
    let pageHeight = this.getPageHeight()

    const newDataList = JSON.parse(JSON.stringify(dataList))

    // 顶部高度
    let tableTop = 0
    if (topClass) {
      const detailTop = document.getElementsByClassName(topClass)[0]
      tableTop =
        detailTop.getBoundingClientRect().bottom -
        detailTop.getBoundingClientRect().top
    }

    // 表头高度
    const detailHeader = document.getElementsByClassName(headerClass)[0]
    const detailHeaderHeight =
      detailHeader.getBoundingClientRect().bottom -
      detailHeader.getBoundingClientRect().top
    const checkDetailList = document.getElementsByClassName(mainClass)

    // 循环检查表
    checkDetailList.forEach((checkDetail, index) => {
      const setInfo = newDataList[index]
      if (!setInfo) {
        return
      }
      let pageIndex = 1
      let bufferHeight = detailHeaderHeight + tableTop
      let totalHeight = detailHeaderHeight + tableTop
      const detailList = checkDetail.getElementsByClassName(rowClass)

      // 循环检查项目
      detailList.forEach((detail, detailIndex) => {
        const setDetail = setInfo[dataKey][detailIndex]
        if (!setDetail) {
          return
        }
        // 计算检查明细项高度
        // 当前项占用高度
        const rect = detail.getBoundingClientRect()
        setDetail.height = rect.bottom - rect.top
        // 如果当前项目高度已经超过1页，则当前项的前面不分页
        if (setDetail.height + detailHeaderHeight > pageHeight) {
          setDetail.pageIndex = pageIndex
          bufferHeight += setDetail.height
          totalHeight += setDetail.height
          if (bufferHeight > pageHeight) {
            bufferHeight = bufferHeight % pageHeight
          }
          pageIndex = Math.floor(totalHeight / pageHeight)
          setDetail.pageIndex = pageIndex
          setDetail.multiPages = true
          return
        }
        // 如果当前项目没有超过1页，则判断当页是否有足够高度
        if (bufferHeight + setDetail.height > pageHeight) {
          // 如果当前放不下，则放到下一页
          totalHeight += pageHeight - bufferHeight
          setDetail.blankHeight = pageHeight - bufferHeight
          // 下一页插入表头高度和自己的高度
          bufferHeight = detailHeaderHeight + setDetail.height
          totalHeight += detailHeaderHeight + setDetail.height
          pageIndex++
        } else {
          // 如果当前页能放下，则放在当前页
          totalHeight += setDetail.height
          bufferHeight += setDetail.height
        }
        setDetail.pageIndex = pageIndex
        setDetail.multiPages = false
      })
      // 合并在同一页的大项目
      setInfo[dataKey] = this.mergeList(setInfo[dataKey])
    })

    return newDataList
  }

  // 合并相同大项目的明细
  mergeList(setDetailList) {
    let result = []
    let prevPageIndex = null
    let prevItemCategory = null
    let prevMultiPages = false
    for (const setDetail of setDetailList) {
      // 如果当前项和上一项在同一页，并且大项目相同，则合并
      if (
        prevPageIndex === setDetail.pageIndex &&
        prevItemCategory === setDetail.item_ategory &&
        !prevMultiPages &&
        !setDetail.multiPages
      ) {
        const group = result[result.length - 1]
        group.height += setDetail.height
        group.children.push(setDetail.children[0])
      } else {
        result.push({
          item_ategory: setDetail.item_ategory,
          item_ategory_list: setDetail.item_ategory_list,
          pageIndex: setDetail.pageIndex,
          height: setDetail.height,
          blankHeight: setDetail.blankHeight,
          children: [setDetail.children[0]],
        })
      }
      prevPageIndex = setDetail.pageIndex
      prevItemCategory = setDetail.item_ategory
      prevMultiPages = setDetail.multiPages
    }
    return result
  }

  splitPages() {
    let pageHeight = this.getPageHeight()
    // 获取分割dom，此处为class类名为item的dom
    let domList = document.getElementsByClassName(this.splitClassName)
    // 进行分割操作，当dom内容已超出a4的高度，则将该dom前插入一个空dom，把他挤下去，分割
    let eleBounding = this.ele.getBoundingClientRect()

    // let domDataList = []
    // for (let i = 0; i < domList.length; i++) {
    //   let nodeData = {}
    //   let node = domList[i]
    //   let bound = node.getBoundingClientRect()
    //   let offset2Ele = bound.top - eleBounding.top // 当前元素头部位于整个报表的相对位置
    //   nodeData.currentTopPage = Math.ceil(offset2Ele / pageHeight) // 当前元素头部在第几页
    //   nodeData.currentBottomPage = Math.ceil(
    //     (bound.bottom - eleBounding.top) / pageHeight
    //   ) //当前元素尾部在哪一页
    //   nodeData.className = node.className
    // }

    for (let i = 0; i < domList.length; i++) {
      debugger
      let node = domList[i]
      let bound = node.getBoundingClientRect()
      let offset2Ele = bound.top - eleBounding.top
      let currentPage = Math.ceil((bound.bottom - eleBounding.top) / pageHeight) //当前元素尾在哪一页
      // 强制分页
      if (node.className.indexOf(this.breakClassName) > -1) {
        let newNode = document.createElement('div')
        newNode.className = 'emptyDiv'
        newNode.style.background = 'white'
        newNode.style.height = pageHeight - (offset2Ele % pageHeight) + 'px'
        newNode.style.width = '100%'
        let divParent = node.parentNode
        divParent.insertBefore(newNode, node)
        continue
      }
      if (Math.ceil(offset2Ele / pageHeight) < currentPage) {
        let newNode = document.createElement('div')
        newNode.className = 'emptyDiv'
        newNode.style.background = 'white'
        newNode.style.height = pageHeight - (offset2Ele % pageHeight) + 'px'
        newNode.style.width = '100%'
        let divParent = domList[i].parentNode // 获取该div的父节点
        divParent.insertBefore(newNode, node)
      }
    }
  }
}

export default PdfLoader
